package top.shaozuo.simple.configuration.microprofile.config.source;

import static java.util.Collections.sort;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ServiceLoader;

import org.eclipse.microprofile.config.spi.ConfigSource;

public class ConfigSources implements Iterable<ConfigSource> {

	private boolean addedDefaultConfigSources;

	private boolean addedDiscoveredConfigSources;

	/**
	 * 内部可变的集合，不要直接暴露在外面
	 */
	private List<ConfigSource> configSources = new LinkedList<>();

	private ClassLoader classLoader;

	public ConfigSources(ClassLoader classLoader) {
		this.classLoader = classLoader;
	}

	public ClassLoader getClassLoader() {
		return classLoader;
	}

	public void setClassLoader(ClassLoader classLoader) {
		this.classLoader = classLoader;
	}

	private static Comparator<ConfigSource> configSourceComparator = new Comparator<ConfigSource>() {
		@Override
		public int compare(ConfigSource o1, ConfigSource o2) {
			return Integer.compare(o2.getOrdinal(), o1.getOrdinal());
		}
	};

	public void addDefaultSources() {
		if (addedDefaultConfigSources) {
			return;
		}
		configSources.add(new FilePropertiesConfigSource());
		configSources.add(new JavaSystemPropertiesConfigSource());
		configSources.add(new OsEnvironmentConfigSource());
		sort(this.configSources, configSourceComparator);
		addedDefaultConfigSources = true;
	}

	public void addDiscoveredSources() {
		if (addedDiscoveredConfigSources) {
			return;
		}
		ServiceLoader<ConfigSource> serviceLoader = ServiceLoader.load(ConfigSource.class, classLoader);
		serviceLoader.forEach(configSources::add);
		// 排序
		sort(this.configSources, configSourceComparator);
		addedDiscoveredConfigSources = true;
	}

	public void addConfigSources(ConfigSource[] sources) {
		addConfigSources(Arrays.asList(sources));
	}

	public void addConfigSources(Iterable<? extends ConfigSource> sources) {
		sources.forEach(this.configSources::add);
		sort(this.configSources, configSourceComparator);
	}

	@Override
	public Iterator<ConfigSource> iterator() {
		return configSources.iterator();
	}

}
